#include <gtk/gtk.h>

#include <base/BLog.h>
#include <base/DebugObject.h>
#include <system/BNetwork.h>
#include <system/BReactor.h>
#include <system/BTime.h>
#include <ncdgui/ServerInterface.h>

#include "IfList.h"
#include "IfListController.h"

#include <generated/blog_channel_ncdgui.h>

#define REQUEST_ADDR NCDREQUESTCLIENT_UNIX_ADDR("/var/run/ncd-request.socket")
//#define REQUEST_ADDR NCDREQUESTCLIENT_UNIX_ADDR("/home/ambro/request.socket")

static gboolean window_delete_event (GtkWidget *widget, GdkEvent  *event, gpointer data);
static void tray_icon_activate (GtkStatusIcon *status_icon, gpointer user_data);
static void tray_icon_popup_menu (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data);
static void popup_menu_status_item_activate (GtkMenuItem *item, gpointer window);
static void popup_menu_exit_item_activate (GtkMenuItem *item, gpointer window);
static void show_window (void);
static void hide_window (void);

BReactor reactor;
ServerInterface srv_if;
IfList list;
IfListController list_cntrl;
GtkWidget *window;
gboolean window_shown;
gboolean window_have_hidden_pos;
gint window_hidden_x;
gint window_hidden_y;
GtkWidget *popup_menu;

enum {
    NAME_COL,
    STATE_COL,
    N_COLS
};

int main (int argc, char *argv[])
{
    int res = 1;
    
    BLog_InitStdout();
    
    BTime_Init();
    
    if (!BNetwork_GlobalInit()) {
        BLog(BLOG_ERROR, "BNetwork_GlobalInit failed");
        goto fail1;
    }
    
    if (!BReactor_Init(&reactor)) {
        BLog(BLOG_ERROR, "BReactor_Init failed");
        goto fail1;
    }
    
    if (!ServerInterface_Init(&srv_if, REQUEST_ADDR, &reactor)) {
        BLog(BLOG_ERROR, "ServerInterface_Init failed");
        goto fail2;
    }
    
    gtk_init(&argc, &argv);
    
    // init window
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "delete-event", G_CALLBACK(window_delete_event), NULL);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    gtk_window_set_default_size(GTK_WINDOW(window), 300, 160);
    gtk_window_set_title(GTK_WINDOW(window), "Network Status");
    window_shown = FALSE;
    window_have_hidden_pos = FALSE;
    
    // init IfList
    IfList_Init(&list);
    GtkWidget *wgt = IfList_Widget(&list);
    gtk_container_add(GTK_CONTAINER(window), wgt);
    gtk_widget_show(wgt);
    
    // init tray icon
    GtkStatusIcon *tray_icon = gtk_status_icon_new();
    g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_activate), NULL);
    g_signal_connect(G_OBJECT(tray_icon), "popup-menu", G_CALLBACK(tray_icon_popup_menu), NULL);
    
    // init popup menu
    popup_menu = gtk_menu_new();
    GtkWidget *menu_item_status = gtk_image_menu_item_new_with_label("Status");
    GtkWidget *menu_item_exit = gtk_image_menu_item_new_with_label("Exit");
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item_exit), gtk_image_new_from_icon_name("application-exit", GTK_ICON_SIZE_MENU));
    g_signal_connect(G_OBJECT(menu_item_status), "activate", G_CALLBACK(popup_menu_status_item_activate), NULL);
    g_signal_connect(G_OBJECT(menu_item_exit), "activate", G_CALLBACK(popup_menu_exit_item_activate), NULL);
    gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), menu_item_status);
    gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), menu_item_exit);
    gtk_widget_show_all(popup_menu);
    
    // init controller
    IfListController_Init(&list_cntrl, &srv_if, &list, tray_icon);
    
    // show tray icon
    gtk_status_icon_set_visible(tray_icon, TRUE);
    
    res = BReactor_Exec(&reactor);
    
    IfListController_Free(&list_cntrl);
    IfList_Free(&list);
    ServerInterface_Free(&srv_if);
fail2:
    BReactor_Free(&reactor);
fail1:
    BLog_Free();
    DebugObjectGlobal_Finish();
    return res;
}

static gboolean window_delete_event (GtkWidget *widget, GdkEvent  *event, gpointer data)
{
    hide_window();
    
    return TRUE;
}

static void tray_icon_activate (GtkStatusIcon *status_icon, gpointer user_data)
{
    if (window_shown) {
        hide_window();
    } else {
        show_window();
    }
}

static void tray_icon_popup_menu (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data)
{
    gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, gtk_status_icon_position_menu, status_icon, button, activate_time);
}

static void popup_menu_status_item_activate (GtkMenuItem *item, gpointer window)
{
    show_window();
}

static void popup_menu_exit_item_activate (GtkMenuItem *item, gpointer window)
{
    BReactor_Quit(&reactor, 0);
}

static void show_window (void)
{
    if (window_shown) {
        return;
    }
    
    if (window_have_hidden_pos) {
        gtk_window_move(GTK_WINDOW(window), window_hidden_x, window_hidden_y);
    }
    
    gtk_widget_show(window);
    window_shown = TRUE;
}

static void hide_window (void)
{
    if (!window_shown) {
        return;
    }
    
    gtk_window_get_position(GTK_WINDOW(window), &window_hidden_x, &window_hidden_y);
    gtk_widget_hide(window);
    window_shown = FALSE;
    window_have_hidden_pos = TRUE;
}
